package com.keyin.protocol;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;

import com.keyin.App;
import com.keyin.android.cache.Cache;
import com.keyin.android.cache.FileDiskCache;
import com.keyin.android.net.Callback;
import com.keyin.android.net.Http;
import com.keyin.android.net.Param;
import com.keyin.android.util.Base64;
import com.keyin.android.util.Tools;

public class CacheImageProtocol {

	private static HashMap<String, ArrayList<Object>> penddingBitmaps = new HashMap<String, ArrayList<Object>>();

	private Param param;
	private Context context;

	private Http http;

	private String url;

	private static FileDiskCache imgCache;

	static {
		imgCache = new FileDiskCache(App.root);
	}

	public CacheImageProtocol(Context context, String url) {

		this.context = context;
		this.url = url;
	}

	public Param getParam() {
		if (this.param == null) {
			param = new Param();
		}
		return param;
	}

	public void startTrans(Object imgHolder) {
		Log.d("CacheImage", url);
		Object cache = Cache.get(url);
		if (cache != null) {
			fillImageHolder(imgHolder, (Bitmap) cache);
			return;
		}

		cache = imgCache.get(encode(url));
		if (cache != null) {
			byte[] data = (byte[]) cache;
			Bitmap bm = BitmapFactory.decodeByteArray(data, 0, data.length);
			Cache.put(url, bm);

			fillImageHolder(imgHolder, bm);
			return;
		}
		synchronized (penddingBitmaps) {

			ArrayList<Object> objs = penddingBitmaps.get(url);
			if (objs == null) {
				objs = new ArrayList<Object>();
				penddingBitmaps.put(url, objs);

				http = new Http(new ImageCallback(url));
				http.start();
			}
			objs.add(imgHolder);
		}
	}

	/**
	 * @param imgHolder
	 * @param bm
	 */
	private void fillImageHolder(Object imgHolder, Bitmap bm) {
		if (imgHolder instanceof ImageView) {
			ImageView imgView = (ImageView) imgHolder;
			// imgView.setImageBitmap(bm);

			Message msg = new Message();
			msg.obj = new Object[] { imgView, bm };
			handle.sendMessage(msg);
		} else if (imgHolder instanceof Reciever) {
			Reciever re = (Reciever) imgHolder;
			re.onRecieve(bm);
		}
	}

	private static final Handler handle = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			Object[] obj = (Object[]) msg.obj;
			ImageView imgView = (ImageView) obj[0];
			Bitmap bitMap = (Bitmap) obj[1];

			imgView.setImageBitmap(bitMap);
		}

	};

	public static String encode(String url) {
		MessageDigest md5;
		try {
			md5 = MessageDigest.getInstance("MD5");
			byte[] b = md5.digest(url.getBytes("utf-8"));
			int i;
			StringBuffer buf = new StringBuffer("");
			for (int offset = 0; offset < b.length; offset++) {
				i = b[offset];
				if (i < 0)
					i += 256;
				if (i < 16)
					buf.append("0");
				buf.append(Integer.toHexString(i));
			}
			System.out.println("result: " + buf.toString());// 32

			return buf.toString();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return "";
	}

	private static String decode(String url)
			throws UnsupportedEncodingException {
		return new String(Base64.decode(url.getBytes("utf-8")), "utf-8");
	}

	private class ImageCallback extends Callback {

		private String imgUri;

		public ImageCallback(String url) {
			imgUri = url;
		}

		@Override
		public Context getContext() {
			return context;
		}

		@Override
		public Param getHeader() {
			return null;
		}

		@Override
		public byte[] getPostParam() {
			return null;
		}

		@Override
		public String getUrl() {
			return imgUri;
		}

		@Override
		public void onException(Exception e) {
			Tools.printException(e);
		}

		@Override
		public void onRecieve(byte[] data) {

			Bitmap bm = null;
			try {
				bm = BitmapFactory.decodeByteArray(data, 0, data.length);
				if (bm == null) {
					throw new NullPointerException(new String(data, "utf-8"));
				}
				imgCache.put(encode(getUrl()), data);

				Cache.put(imgUri, bm);
			} catch (Exception e) {
				onException(e);
			}

			ArrayList<Object> imgHolders = penddingBitmaps.remove(imgUri);
			if (bm == null) {
				return;
			}
			if (imgHolders != null) {
				for (Object imgHolder : imgHolders) {
					fillImageHolder(imgHolder, bm);
				}
			}
		}
	}

	public static interface Reciever {
		public void onRecieve(Bitmap bitmap);
	}
}
